//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package data_anno_task_api_serv

import (
	"context"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/data_anno_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/data_anno_task_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_entry_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *DataAnnoTaskApiImpl) SetResult(ctx context.Context, req *data_anno_task_api.SetResultRequest) (*data_anno_task_api.SetResultResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_task_api.SetResultResponse{
			Code:   data_anno_task_api.SetResultResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if req.Result.MemberUserId == "" {
		req.Result.MemberUserId = sessionItem.UserId
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_task_api.SetResultResponse{
			Code:   data_anno_task_api.SetResultResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_task_api.SetResultResponse{
			Code:   data_anno_task_api.SetResultResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &data_anno_task_api.SetResultResponse{
			Code:   data_anno_task_api.SetResultResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	if sessionItem.UserId != req.Result.MemberUserId {
		entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.Result.AnnoProjectId, req.ProjectId)
		if err != nil {
			return &data_anno_task_api.SetResultResponse{
				Code:   data_anno_task_api.SetResultResponse_CODE_NO_ANNO_PROJECT,
				ErrMsg: "标注项目不存在",
			}, nil
		}
		if entryItem.EntryType != uint32(project_entry_api.ENTRY_TYPE_ENTRY_TYPE_DATA_ANNO) {
			return &data_anno_task_api.SetResultResponse{
				Code:   data_anno_task_api.SetResultResponse_CODE_NO_ANNO_PROJECT,
				ErrMsg: "标注项目不存在",
			}, nil
		}

		hasUpdatePerm := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)

		if !hasUpdatePerm {
			return &data_anno_task_api.SetResultResponse{
				Code:   data_anno_task_api.SetResultResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
	}
	//检查标注项目是否存在
	exist, err := data_anno_dao.AnnoProjectDao.Exist(ctx, req.ProjectId, req.Result.AnnoProjectId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.SetResultResponse{
			Code:   data_anno_task_api.SetResultResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}
	//检查标注用户是否存在
	exist, err = data_anno_dao.AnnoMemberDao.Exist(ctx, req.Result.AnnoProjectId, req.Result.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.SetResultResponse{
			Code:   data_anno_task_api.SetResultResponse_CODE_NO_MEMBER,
			ErrMsg: "标注成员不存在",
		}, nil
	}
	//检查标注任务是否存在
	exist, err = data_anno_dao.AnnoTaskDao.Exist(ctx, req.Result.AnnoProjectId, req.Result.MemberUserId, req.Result.ResourceId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.SetResultResponse{
			Code:   data_anno_task_api.SetResultResponse_CODE_NO_TASK,
			ErrMsg: "标注任务不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		exist, err = data_anno_dao.AnnoResultDao.Exist(sessCtx, req.Result.AnnoProjectId, req.Result.MemberUserId, req.Result.ResourceId)
		if err != nil {
			return nil, err
		}
		if exist {
			err = data_anno_dao.AnnoResultDao.Update(sessCtx, req.Result.AnnoProjectId, req.Result.MemberUserId, req.Result.ResourceId, req.Result.Result)
			if err != nil {
				return nil, err
			}
		} else {
			err = data_anno_dao.AnnoResultDao.Insert(sessCtx, &data_anno_dao.AnnoResultDbItem{
				AnnoProjectId: req.Result.AnnoProjectId,
				MemberUserId:  req.Result.MemberUserId,
				ResourceId:    req.Result.ResourceId,
				Result:        req.Result.Result,
			})
			if err != nil {
				return nil, err
			}
		}
		return &data_anno_task_api.SetResultResponse{
			Code: data_anno_task_api.SetResultResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*data_anno_task_api.SetResultResponse), nil
}

func (apiImpl *DataAnnoTaskApiImpl) SetResultState(ctx context.Context, req *data_anno_task_api.SetResultStateRequest) (*data_anno_task_api.SetResultStateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_task_api.SetResultStateResponse{
			Code:   data_anno_task_api.SetResultStateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if req.MemberUserId == "" {
		req.MemberUserId = sessionItem.UserId
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_task_api.SetResultStateResponse{
			Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_task_api.SetResultStateResponse{
			Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &data_anno_task_api.SetResultStateResponse{
			Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	if sessionItem.UserId != req.MemberUserId {
		entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.AnnoProjectId, req.ProjectId)
		if err != nil {
			return &data_anno_task_api.SetResultStateResponse{
				Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_ANNO_PROJECT,
				ErrMsg: "标注项目不存在",
			}, nil
		}
		if entryItem.EntryType != uint32(project_entry_api.ENTRY_TYPE_ENTRY_TYPE_DATA_ANNO) {
			return &data_anno_task_api.SetResultStateResponse{
				Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_ANNO_PROJECT,
				ErrMsg: "标注项目不存在",
			}, nil
		}

		hasUpdatePerm := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)

		if !hasUpdatePerm {
			return &data_anno_task_api.SetResultStateResponse{
				Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
	}
	//检查标注项目是否存在
	exist, err := data_anno_dao.AnnoProjectDao.Exist(ctx, req.ProjectId, req.AnnoProjectId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.SetResultStateResponse{
			Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}
	//检查标注用户是否存在
	exist, err = data_anno_dao.AnnoMemberDao.Exist(ctx, req.AnnoProjectId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.SetResultStateResponse{
			Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_MEMBER,
			ErrMsg: "标注成员不存在",
		}, nil
	}
	//检查标注任务是否存在
	exist, err = data_anno_dao.AnnoTaskDao.Exist(ctx, req.AnnoProjectId, req.MemberUserId, req.ResourceId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.SetResultStateResponse{
			Code:   data_anno_task_api.SetResultStateResponse_CODE_NO_TASK,
			ErrMsg: "标注任务不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = data_anno_dao.AnnoTaskDao.UpdateDone(sessCtx, req.AnnoProjectId, req.MemberUserId, req.ResourceId, req.Done)
		if err != nil {
			return nil, err
		}
		//更新用户的done计数器
		count, err := data_anno_dao.AnnoTaskDao.CountByMember(sessCtx, req.AnnoProjectId, req.MemberUserId, true, true)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoMemberDao.UpdateDoneCount(sessCtx, req.AnnoProjectId, req.MemberUserId, count)
		if err != nil {
			return nil, err
		}
		//更新项目的done计数器
		count, err = data_anno_dao.AnnoTaskDao.CountByAnnoProject(sessCtx, req.AnnoProjectId, true, true)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoProjectDao.UpdateDoneTaskCount(sessCtx, req.ProjectId, req.AnnoProjectId, count)
		if err != nil {
			return nil, err
		}
		return &data_anno_task_api.SetResultStateResponse{
			Code: data_anno_task_api.SetResultStateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*data_anno_task_api.SetResultStateResponse), nil
}

func (apiImpl *DataAnnoTaskApiImpl) GetResult(ctx context.Context, req *data_anno_task_api.GetResultRequest) (*data_anno_task_api.GetResultResponse, error) {
	emptyResult := &data_anno_task_api.AnnoResult{
		AnnoProjectId: req.AnnoProjectId,
		MemberUserId:  req.MemberUserId,
		ResourceId:    req.ResourceId,
		Result:        "[]",
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Result: emptyResult,
		}, nil
	}
	if req.MemberUserId == "" {
		req.MemberUserId = sessionItem.UserId
		emptyResult.MemberUserId = sessionItem.UserId
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Result: emptyResult,
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Result: emptyResult,
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Result: emptyResult,
		}, nil
	}

	if sessionItem.UserId != req.MemberUserId {
		if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
			return &data_anno_task_api.GetResultResponse{
				Code:   data_anno_task_api.GetResultResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Result: emptyResult,
			}, nil
		}
	}
	//检查标注项目是否存在
	exist, err := data_anno_dao.AnnoProjectDao.Exist(ctx, req.ProjectId, req.AnnoProjectId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
			Result: emptyResult,
		}, nil
	}
	//检查标注用户是否存在
	exist, err = data_anno_dao.AnnoMemberDao.Exist(ctx, req.AnnoProjectId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_NO_MEMBER,
			ErrMsg: "标注成员不存在",
			Result: emptyResult,
		}, nil
	}
	//检查标注任务是否存在
	exist, err = data_anno_dao.AnnoTaskDao.Exist(ctx, req.AnnoProjectId, req.MemberUserId, req.ResourceId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_NO_TASK,
			ErrMsg: "标注任务不存在",
			Result: emptyResult,
		}, nil
	}
	//检查结果是否存在
	exist, err = data_anno_dao.AnnoResultDao.Exist(ctx, req.AnnoProjectId, req.MemberUserId, req.ResourceId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.GetResultResponse{
			Code: data_anno_task_api.GetResultResponse_CODE_OK,
			Result: &data_anno_task_api.AnnoResult{
				AnnoProjectId: req.AnnoProjectId,
				MemberUserId:  req.MemberUserId,
				ResourceId:    req.ResourceId,
				Result:        "[]",
			},
		}, nil
	} else {
		resultItem, err := data_anno_dao.AnnoResultDao.Get(ctx, req.AnnoProjectId, req.MemberUserId, req.ResourceId)
		if err != nil {
			return nil, err
		}
		return &data_anno_task_api.GetResultResponse{
			Code:   data_anno_task_api.GetResultResponse_CODE_OK,
			Result: resultItem.ToAnnoResult(),
		}, nil
	}
}
